Packages

library(plyr)
library(tidyverse)
library(here)
library(geojsonR)
library(janitor)
library(knitr)
library(lubridate) 
library(mapview)
library(gbfs)
library(sf) 
library(tmap)
library(tidycensus)
library(dplyr)
library(conflicted)
library(plotly)
conflicts_prefer(here::here)
[conflicted] Removing existing preference.[conflicted] Will prefer here::here over any other package.
conflicts_prefer(dplyr::rename)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::rename over any other package.
conflicts_prefer(dplyr::filter)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::filter over any other package.
conflicts_prefer(dplyr::mutate)
[conflicted] Removing existing preference.[conflicted] Will prefer dplyr::mutate over any other package.

Reading the files.

Metro Station Entrances to map the location of metro, boarding data to show how many people are using the metro station, and bikeshare to show the number of people riding bikes.

All data is from the month September because there are no major holidays, the weather is still decent enough for people to ride bikes, and the number of tourists/ pleasure bike riders are reduced.

For the purpose of this project, we plan on focusing on the commuters, and plan on creating more bike locations to better suit the number of commuters.

metro <- FROM_GeoJson(here('data_raw', 'Metro_Station_Entrances_in_DC.geojson'))
metroRiders <- read.csv(here( 'Boardings by Route Table_Full Data_data.csv'))
metroLoc <- read.csv(here('data_raw', 'Metro_Stations_Regional.csv')) 

sept_raw <- read_csv(here( '202309-capitalbikeshare-tripdata.csv'))
<<<<<<< HEAD
Rows: 450090 Columns: 13── Column specification ───────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (5): ride_id, rideable_type, start_station_name, end_station_name, member_casual
dbl  (6): start_station_id, end_station_id, start_lat, start_lng, end_lat, end_lng
=======
<<<<<<< HEAD

Rows: 450090 Columns: 13── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (5): ride_id, rideable_type, start_station_name, end_station_name, member_casual
dbl  (6): start_station_id, end_station_id, start_lat, start_lng, end_lat, end_lng
=======

Rows: 450090 Columns: 13-- Column specification ------------------------------
Delimiter: ","
chr  (5): ride_id, rideable_type, start_station_na...
dbl  (6): start_station_id, end_station_id, start_...
>>>>>>> 36321748959043dd50b7a89e48066d2758840639
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed
dttm (2): started_at, ended_at
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
neigh = st_read(here("data_raw", "DC_Health_Planning_Neighborhoods.geojson")) %>% clean_names()
<<<<<<< HEAD
Reading layer `DC_Health_Planning_Neighborhoods' from data source 
  `C:\DATASCIENCE\basta-dataforskare\data_raw\DC_Health_Planning_Neighborhoods.geojson' using driver `GeoJSON'
=======
<<<<<<< HEAD

Reading layer `DC_Health_Planning_Neighborhoods' from data source 
  `C:\Users\avery\Documents\ds241\ds241_f23\basta-dataforskare\basta-dataforskare\data_raw\DC_Health_Planning_Neighborhoods.geojson' 
=======

Reading layer `DC_Health_Planning_Neighborhoods' from data source `C:\Users\benne\OneDrive\Desktop\Intro to Data Science\WORKSPACE\DS241\basta-dataforskare\data_raw\DC_Health_Planning_Neighborhoods.geojson' 
>>>>>>> 36321748959043dd50b7a89e48066d2758840639
  using driver `GeoJSON'
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed
Simple feature collection with 51 features and 8 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: -77.11976 ymin: 38.79165 xmax: -76.9094 ymax: 38.99556
Geodetic CRS:  WGS 84

Cleaning Data

This filters the data so we are only getting entries for the weekdays and not the weekends, appending location variables to station names, and combining repeat stations with a summed amount of entries.

#metroLoc = metroLoc |> 
  #rename("X" = "ï..X")

metroAddy <- subset(metroLoc, select = c(NAME, ADDRESS, X, Y))|>
  rename("Station" = "NAME", "Lon" = "X", "Lat" = "Y")

metroRiders$Time.Period = NULL
metroRiders$Day.of.Week = NULL
metroRiders$Holiday = NULL
metroRiders$Month = NULL
metroRiders$Year = NULL
metroRiders$Avg.Daily.Entries.Rounded = NULL

#metroRiders = metroRiders |>
 #rename("Station" = "ï..Station")

metroR1 <- metroRiders |>
  filter(Servicetype == "Weekday") |>
  ddply("Station", numcolwise(sum))

METRO <- merge(x = metroR1, y = metroAddy, by = "Station")

glimpse(METRO)
<<<<<<< HEAD
Rows: 86
Columns: 5
$ Station <chr> "Anacostia", "Arlington Cemetery", "Ashburn", "Ballston-MU", "Benning Road", "Bethesda", "Bra…
$ Entries <int> 62365, 16111, 25199, 114875, 31518, 102933, 45638, 47644, 85141, 23630, 101604, 10032, 57042,…
$ ADDRESS <chr> "1101 HOWARD ROAD SE, WASHINGTON, DC", "1000 NORTH MEMORIAL DRIVE, ARLINGTON, VA", "43625-A C…
$ Lon     <dbl> -76.99537, -77.06281, -77.49154, -77.11317, -76.93837, -77.09413, -77.05367, -76.91147, -76.9…
$ Lat     <dbl> 38.86297, 38.88469, 39.00529, 38.88219, 38.89098, 38.98440, 38.81415, 38.82645, 38.93322, 38.…
======= <<<<<<< HEAD
Rows: 86
Columns: 5
$ Station <chr> "Anacostia", "Arlington Cemetery", "Ashburn", "Ballston-MU", "Benning Road", "Bethesda", "Braddock Road",…
$ Entries <int> 62365, 16111, 25199, 114875, 31518, 102933, 45638, 47644, 85141, 23630, 101604, 10032, 57042, 47500, 3734…
$ ADDRESS <chr> "1101 HOWARD ROAD SE, WASHINGTON, DC", "1000 NORTH MEMORIAL DRIVE, ARLINGTON, VA", "43625-A CROSON LN, AS…
$ Lon     <dbl> -76.99537, -77.06281, -77.49154, -77.11317, -76.93837, -77.09413, -77.05367, -76.91147, -76.99454, -76.91…
$ Lat     <dbl> 38.86297, 38.88469, 39.00529, 38.88219, 38.89098, 38.98440, 38.81415, 38.82645, 38.93322, 38.88947, 38.88…
=======
Rows: 86
Columns: 5
$ Station <chr> "Anacostia", "Arlington Cemetery", "~
$ Entries <int> 62365, 16111, 25199, 114875, 31518, ~
$ ADDRESS <chr> "1101 HOWARD ROAD SE, WASHINGTON, DC~
$ Lon     <dbl> -76.99537, -77.06281, -77.49154, -77~
$ Lat     <dbl> 38.86297, 38.88469, 39.00529, 38.882~
>>>>>>> 36321748959043dd50b7a89e48066d2758840639 >>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed

Cleaning bike data

bikeR1 is the data set originated from September Bikeshare data. It is filtered to keep the columns “started at”, “start lat” and “start_lng”. Na.omit gets rid of everything null, and mutate adds the date to when each bike ride started.

bikeR2 is a further filtering of bikeR1 where coordinates are added so we can map out the bike riders starting location.

bikeR3 is the new data set where bikeR2 and neigh are joined.

bikeR1 = sept_raw %>% select(started_at, start_lat, start_lng) %>% na.omit() %>% mutate(start_date=as.Date(started_at)) %>% select(start_date, start_lat, start_lng)

bikeR2 = bikeR1 %>% st_as_sf(coords=c("start_lng", "start_lat"), crs=4326)

st_crs(neigh$geometry[1])
Coordinate Reference System:
  User input: WGS 84 
  wkt:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
bikeR3 = bikeR2 %>% st_join(neigh)


 
#code for possible future mapping 
#df1_s_sf = df1_s %>% st_as_sf(coords =c("start_lng", "start_lat"), crs = 4326)

Metro Map

The first part of this code chunk is converting the metro data frame into a spatial data frame.

MetroMap2 is a filtration of MetroMap that joins the data set “neigh” and omits any null values. Then a variable ‘code’ is added to the numcolwise. There are 50 ‘codes’ created in this process. Then from those codes, we will determine rideship for both bikes and metro.

MetroMap <- st_as_sf(METRO, coords = c("Lon", "Lat"), crs =4326)

MetroMap2 <- MetroMap %>%
  st_join(neigh) %>% na.omit() %>%
  ddply("code", numcolwise(sum))

More Filtering

neigh1 is the new data frame of “neigh” where code and geometry are the chosen variables to be kept.

bike R4 is a further filtration of bikeR3, where start date, code, geometry is kept and geometry column is dropped.

bikeR5 is another filter of neigh1, where bikeR4 is added (joined). Additionally, each of the weekend dates are removed from the data set as we chose to only look at weekday data.


neigh1 = neigh %>% select(code, geometry)

bikeR4 = bikeR3 %>% select(start_date, code, geometry) %>% st_drop_geometry()

bikeR5 = neigh1 %>% full_join(bikeR4) %>% filter(start_date != as.Date('2023-09-02')) %>% filter(start_date != as.Date('2023-09-03')) %>% filter(start_date != as.Date('2023-09-09')) %>% filter(start_date != as.Date('2023-09-10')) %>% filter(start_date != as.Date('2023-09-16')) %>% filter(start_date != as.Date('2023-09-17')) %>% filter(start_date != as.Date('2023-09-23')) %>% filter(start_date != as.Date('2023-09-24')) %>% filter(start_date != as.Date('2023-09-30'))
Joining with `by = join_by(code)`

And More!

bikeR6 is a nre data frame where we took the bike data from set bikeR5. bikeR6 has 51 codes and they are listed as observations. All null values are ommitted.

bikeR7 takes the data from bikeR6 and keeps the code as well as frequency and renames it to bike_freq.

#plot(neigh)

bikeR6 = data.frame(table(bikeR5$code)) %>% rename(code=Var1) %>% full_join(bikeR5) %>% select(code, Freq, geometry) %>% distinct() %>% na.omit()
Joining with `by = join_by(code)`
bikeR7 = bikeR6 %>% select (code, Freq) %>% rename(bike_freq = Freq)

MetroMap3 = MetroMap2 %>% select(Entries, code) %>% rename(metro_freq = Entries)

metro_bike_df = bikeR7 %>% full_join(MetroMap3) %>% mutate(metro_freq = replace_na(metro_freq, 0))
Joining with `by = join_by(code)`
#bikeR7 = bikeR5 %>% count(code, start_date)

#plot(bikeR6)

Last One!

bikeR8 takes bikeR6 and keeps the code and frequency. It also creates a column called bike because all the data in this set is from bike riders. We will use this column later when we make our visual.

MetroMap4 continues the filtration of MetroMap2 where entries (later renamed to freq) and code are kept. Every data in this set is given the variable ‘metro’ as they represent a metro rider.

bikeR8 = bikeR6 %>% select (code, Freq) %>% rename(freq = Freq) %>% mutate(transport = 'bike')

MetroMap4 = MetroMap2 %>% select(Entries, code) %>% rename(freq = Entries) %>% mutate(transport = 'metro')

code = c("N1", "N10", "N11", "N14", "N15", "N16", "N2", "N20", "N21", "N22", "N26", "N27", "N28", "N3", "N32", "N33", "N34", "N36", "N37", "N4", "N40", "N41", "N45", "N46", "N47", "N49", "N5", "N50", "N51", "N6", "N8")

freq = c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)

transport = c('metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro', 'metro')

metroExtra = data.frame(code, freq, transport)

MetroMap4 = MetroMap4 %>% rbind(metroExtra)

metro_bike_df2 = bikeR8 %>% full_join(MetroMap4)
Joining with `by = join_by(code, freq, transport)`

Mapping Metro

This is a simple visual of the metro station locations in DC.

entrances=st_read(here("Metro_Station_Entrances_in_DC.geojson")) %>% clean_names()
<<<<<<< HEAD
Reading layer `Metro_Station_Entrances_in_DC' from data source 
  `C:\DATASCIENCE\basta-dataforskare\Metro_Station_Entrances_in_DC.geojson' using driver `GeoJSON'
=======
<<<<<<< HEAD

Reading layer `Metro_Station_Entrances_in_DC' from data source 
  `C:\Users\avery\Documents\ds241\ds241_f23\basta-dataforskare\basta-dataforskare\Metro_Station_Entrances_in_DC.geojson' 
=======

Reading layer `Metro_Station_Entrances_in_DC' from data source `C:\Users\benne\OneDrive\Desktop\Intro to Data Science\WORKSPACE\DS241\basta-dataforskare\Metro_Station_Entrances_in_DC.geojson' 
>>>>>>> 36321748959043dd50b7a89e48066d2758840639
  using driver `GeoJSON'
>>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed
Simple feature collection with 113 features and 23 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: -77.08577 ymin: 38.84465 xmax: -76.93472 ymax: 38.97578
Geodetic CRS:  WGS 84
class(entrances)
[1] "sf"         "data.frame"
plot(entrances)
Warning: plotting the first 10 out of 23 attributes; use max.plot = 23 to plot all
<<<<<<< HEAD

======= <<<<<<< HEAD

=======

>>>>>>> 36321748959043dd50b7a89e48066d2758840639 >>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed

Mapping Bike Data

We create a gg plot of the data from above. The combined data set of metro and bike riders (metro_bike_df2). We wanted to visualize the number of people who are riding the metro vs using bikes in each of the ‘codes’.

<<<<<<< HEAD

ggplot(metro_bike_df2, aes(fill=transport, y=freq, x=code)) + geom_bar(position='dodge', stat='identity')

=======
charts <- ggplot(metro_bike_df2, aes(fill=transport, y=freq, x=code)) + geom_bar(position='dodge', stat='identity')

ggplotly(charts)
<<<<<<< HEAD =======
NA
>>>>>>> 36321748959043dd50b7a89e48066d2758840639 >>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed

Recommednation:

Based on the data comaprisons of metro entries adn bike entries, we would recommend that the bikeshare group look into increasing the amount of bike stations in neighboorhoods: n1, n2, n3, n4, n6, n8, n10, n11, n14, n15, n16, n20, n21, n22, n26, n27, n28, n32, n33, n34, n36, n37, n40, n41, n45, n46, n47, n49, n50, n51.

<<<<<<< HEAD
LS0tDQp0aXRsZTogIkZpbmFsIFByb2plY3QiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBQYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocGx5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShoZXJlKQ0KbGlicmFyeShnZW9qc29uUikNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgDQpsaWJyYXJ5KG1hcHZpZXcpDQpsaWJyYXJ5KGdiZnMpDQpsaWJyYXJ5KHNmKSANCmxpYnJhcnkodG1hcCkNCmxpYnJhcnkodGlkeWNlbnN1cykNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGNvbmZsaWN0ZWQpDQpsaWJyYXJ5KHBsb3RseSkNCmNvbmZsaWN0c19wcmVmZXIoaGVyZTo6aGVyZSkNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OnJlbmFtZSkNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OmZpbHRlcikNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6Om11dGF0ZSkNCg0KYGBgDQoNCiMjIFJlYWRpbmcgdGhlIGZpbGVzLg0KDQpNZXRybyBTdGF0aW9uIEVudHJhbmNlcyB0byBtYXAgdGhlIGxvY2F0aW9uIG9mIG1ldHJvLCBib2FyZGluZyBkYXRhIHRvIHNob3cgaG93IG1hbnkgcGVvcGxlIGFyZSB1c2luZyB0aGUgbWV0cm8gc3RhdGlvbiwgYW5kIGJpa2VzaGFyZSB0byBzaG93IHRoZSBudW1iZXIgb2YgcGVvcGxlIHJpZGluZyBiaWtlcy4NCg0KQWxsIGRhdGEgaXMgZnJvbSB0aGUgbW9udGggU2VwdGVtYmVyIGJlY2F1c2UgdGhlcmUgYXJlIG5vIG1ham9yIGhvbGlkYXlzLCB0aGUgd2VhdGhlciBpcyBzdGlsbCBkZWNlbnQgZW5vdWdoIGZvciBwZW9wbGUgdG8gcmlkZSBiaWtlcywgYW5kIHRoZSBudW1iZXIgb2YgdG91cmlzdHMvIHBsZWFzdXJlIGJpa2UgcmlkZXJzIGFyZSByZWR1Y2VkLg0KDQpGb3IgdGhlIHB1cnBvc2Ugb2YgdGhpcyBwcm9qZWN0LCB3ZSBwbGFuIG9uIGZvY3VzaW5nIG9uIHRoZSBjb21tdXRlcnMsIGFuZCBwbGFuIG9uIGNyZWF0aW5nIG1vcmUgYmlrZSBsb2NhdGlvbnMgdG8gYmV0dGVyIHN1aXQgdGhlIG51bWJlciBvZiBjb21tdXRlcnMuDQoNCmBgYHtyfQ0KbWV0cm8gPC0gRlJPTV9HZW9Kc29uKGhlcmUoJ2RhdGFfcmF3JywgJ01ldHJvX1N0YXRpb25fRW50cmFuY2VzX2luX0RDLmdlb2pzb24nKSkNCm1ldHJvUmlkZXJzIDwtIHJlYWQuY3N2KGhlcmUoJ2RhdGFfcmF3JywgJ0JvYXJkaW5ncyBieSBSb3V0ZSBUYWJsZV9GdWxsIERhdGFfZGF0YS5jc3YnKSkNCm1ldHJvTG9jIDwtIHJlYWQuY3N2KGhlcmUoJ2RhdGFfcmF3JywgJ01ldHJvX1N0YXRpb25zX1JlZ2lvbmFsLmNzdicpKSANCg0Kc2VwdF9yYXcgPC0gcmVhZF9jc3YoaGVyZSgnZGF0YV9yYXcnLCAnMjAyMzA5LWNhcGl0YWxiaWtlc2hhcmUtdHJpcGRhdGEuY3N2JykpDQoNCm5laWdoID0gc3RfcmVhZChoZXJlKCJkYXRhX3JhdyIsICJEQ19IZWFsdGhfUGxhbm5pbmdfTmVpZ2hib3Job29kcy5nZW9qc29uIikpICU+JSBjbGVhbl9uYW1lcygpDQoNCmBgYA0KDQojIyBDbGVhbmluZyBEYXRhDQoNClRoaXMgZmlsdGVycyB0aGUgZGF0YSBzbyB3ZSBhcmUgb25seSBnZXR0aW5nIGVudHJpZXMgZm9yIHRoZSB3ZWVrZGF5cyBhbmQgbm90IHRoZSB3ZWVrZW5kcywgYXBwZW5kaW5nIGxvY2F0aW9uIHZhcmlhYmxlcyB0byBzdGF0aW9uIG5hbWVzLCBhbmQgY29tYmluaW5nIHJlcGVhdCBzdGF0aW9ucyB3aXRoIGEgc3VtbWVkIGFtb3VudCBvZiBlbnRyaWVzLg0KDQpgYGB7cn0NCiNtZXRyb0xvYyA9IG1ldHJvTG9jIHw+IA0KICAjcmVuYW1lKCJYIiA9ICLDry4uWCIpDQoNCm1ldHJvQWRkeSA8LSBzdWJzZXQobWV0cm9Mb2MsIHNlbGVjdCA9IGMoTkFNRSwgQUREUkVTUywgWCwgWSkpfD4NCiAgcmVuYW1lKCJTdGF0aW9uIiA9ICJOQU1FIiwgIkxvbiIgPSAiWCIsICJMYXQiID0gIlkiKQ0KDQptZXRyb1JpZGVycyRUaW1lLlBlcmlvZCA9IE5VTEwNCm1ldHJvUmlkZXJzJERheS5vZi5XZWVrID0gTlVMTA0KbWV0cm9SaWRlcnMkSG9saWRheSA9IE5VTEwNCm1ldHJvUmlkZXJzJE1vbnRoID0gTlVMTA0KbWV0cm9SaWRlcnMkWWVhciA9IE5VTEwNCm1ldHJvUmlkZXJzJEF2Zy5EYWlseS5FbnRyaWVzLlJvdW5kZWQgPSBOVUxMDQoNCiNtZXRyb1JpZGVycyA9IG1ldHJvUmlkZXJzIHw+DQogI3JlbmFtZSgiU3RhdGlvbiIgPSAiw68uLlN0YXRpb24iKQ0KDQptZXRyb1IxIDwtIG1ldHJvUmlkZXJzIHw+DQogIGZpbHRlcihTZXJ2aWNldHlwZSA9PSAiV2Vla2RheSIpIHw+DQogIGRkcGx5KCJTdGF0aW9uIiwgbnVtY29sd2lzZShzdW0pKQ0KDQpNRVRSTyA8LSBtZXJnZSh4ID0gbWV0cm9SMSwgeSA9IG1ldHJvQWRkeSwgYnkgPSAiU3RhdGlvbiIpDQoNCmdsaW1wc2UoTUVUUk8pDQoNCmBgYA0KDQpDbGVhbmluZyBiaWtlIGRhdGENCg0KYGBge3J9DQpiaWtlUjEgPSBzZXB0X3JhdyAlPiUgc2VsZWN0KHN0YXJ0ZWRfYXQsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKSAlPiUgbmEub21pdCgpICU+JSBtdXRhdGUoc3RhcnRfZGF0ZT1hcy5EYXRlKHN0YXJ0ZWRfYXQpKSAlPiUgc2VsZWN0KHN0YXJ0X2RhdGUsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKQ0KDQpiaWtlUjIgPSBiaWtlUjEgJT4lIHN0X2FzX3NmKGNvb3Jkcz1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycz00MzI2KQ0KDQpzdF9jcnMobmVpZ2gkZ2VvbWV0cnlbMV0pDQoNCmJpa2VSMyA9IGJpa2VSMiAlPiUgc3Rfam9pbihuZWlnaCkNCg0KDQogDQojY29kZSBmb3IgcG9zc2libGUgZnV0dXJlIG1hcHBpbmcgDQojZGYxX3Nfc2YgPSBkZjFfcyAlPiUgc3RfYXNfc2YoY29vcmRzID1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycyA9IDQzMjYpDQpgYGANCg0KYGBge3J9DQpNZXRyb01hcCA8LSBzdF9hc19zZihNRVRSTywgY29vcmRzID0gYygiTG9uIiwgIkxhdCIpLCBjcnMgPTQzMjYpDQoNCk1ldHJvTWFwMiA8LSBNZXRyb01hcCAlPiUNCiAgc3Rfam9pbihuZWlnaCkgJT4lIG5hLm9taXQoKSAlPiUNCiAgZGRwbHkoImNvZGUiLCBudW1jb2x3aXNlKHN1bSkpDQpgYGANCg0KDQpgYGB7cn0NCg0KbmVpZ2gxID0gbmVpZ2ggJT4lIHNlbGVjdChjb2RlLCBnZW9tZXRyeSkNCg0KYmlrZVI0ID0gYmlrZVIzICU+JSBzZWxlY3Qoc3RhcnRfZGF0ZSwgY29kZSwgZ2VvbWV0cnkpICU+JSBzdF9kcm9wX2dlb21ldHJ5KCkNCg0KYmlrZVI1ID0gbmVpZ2gxICU+JSBmdWxsX2pvaW4oYmlrZVI0KSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wMicpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wMycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wOScpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xMCcpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xNicpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xNycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0yMycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0yNCcpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0zMCcpKQ0KYGBgDQoNCmBgYHtyfQ0KI3Bsb3QobmVpZ2gpDQoNCmJpa2VSNiA9IGRhdGEuZnJhbWUodGFibGUoYmlrZVI1JGNvZGUpKSAlPiUgcmVuYW1lKGNvZGU9VmFyMSkgJT4lIGZ1bGxfam9pbihiaWtlUjUpICU+JSBzZWxlY3QoY29kZSwgRnJlcSwgZ2VvbWV0cnkpICU+JSBkaXN0aW5jdCgpICU+JSBuYS5vbWl0KCkNCg0KYmlrZVI3ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoYmlrZV9mcmVxID0gRnJlcSkNCg0KTWV0cm9NYXAzID0gTWV0cm9NYXAyICU+JSBzZWxlY3QoRW50cmllcywgY29kZSkgJT4lIHJlbmFtZShtZXRyb19mcmVxID0gRW50cmllcykNCg0KbWV0cm9fYmlrZV9kZiA9IGJpa2VSNyAlPiUgZnVsbF9qb2luKE1ldHJvTWFwMykgJT4lIG11dGF0ZShtZXRyb19mcmVxID0gcmVwbGFjZV9uYShtZXRyb19mcmVxLCAwKSkNCg0KI2Jpa2VSNyA9IGJpa2VSNSAlPiUgY291bnQoY29kZSwgc3RhcnRfZGF0ZSkNCg0KI3Bsb3QoYmlrZVI2KQ0KYGBgDQoNCmBgYHtyfQ0KYmlrZVI4ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoZnJlcSA9IEZyZXEpICU+JSBtdXRhdGUodHJhbnNwb3J0ID0gJ2Jpa2UnKQ0KDQpNZXRyb01hcDQgPSBNZXRyb01hcDIgJT4lIHNlbGVjdChFbnRyaWVzLCBjb2RlKSAlPiUgcmVuYW1lKGZyZXEgPSBFbnRyaWVzKSAlPiUgbXV0YXRlKHRyYW5zcG9ydCA9ICdtZXRybycpDQoNCmNvZGUgPSBjKCJOMSIsICJOMTAiLCAiTjExIiwgIk4xNCIsICJOMTUiLCAiTjE2IiwgIk4yIiwgIk4yMCIsICJOMjEiLCAiTjIyIiwgIk4yNiIsICJOMjciLCAiTjI4IiwgIk4zIiwgIk4zMiIsICJOMzMiLCAiTjM0IiwgIk4zNiIsICJOMzciLCAiTjQiLCAiTjQwIiwgIk40MSIsICJONDUiLCAiTjQ2IiwgIk40NyIsICJONDkiLCAiTjUiLCAiTjUwIiwgIk41MSIsICJONiIsICJOOCIpDQoNCmZyZXEgPSBjKDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDApDQoNCnRyYW5zcG9ydCA9IGMoJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJykNCg0KbWV0cm9FeHRyYSA9IGRhdGEuZnJhbWUoY29kZSwgZnJlcSwgdHJhbnNwb3J0KQ0KDQpNZXRyb01hcDQgPSBNZXRyb01hcDQgJT4lIHJiaW5kKG1ldHJvRXh0cmEpDQoNCm1ldHJvX2Jpa2VfZGYyID0gYmlrZVI4ICU+JSBmdWxsX2pvaW4oTWV0cm9NYXA0KQ0KDQpgYGANCg0KDQojIyBNYXBwaW5nIE1ldHJvDQoNCmBgYHtyfQ0KZW50cmFuY2VzPXN0X3JlYWQoaGVyZSgiTWV0cm9fU3RhdGlvbl9FbnRyYW5jZXNfaW5fREMuZ2VvanNvbiIpKSAlPiUgY2xlYW5fbmFtZXMoKQ0KDQpjbGFzcyhlbnRyYW5jZXMpDQoNCnBsb3QoZW50cmFuY2VzKQ0KYGBgDQoNCiMjIE1hcHBpbmcgQmlrZSBEYXRhDQoNCg0KYGBge3J9DQpjaGFydHMgPC0gZ2dwbG90KG1ldHJvX2Jpa2VfZGYyLCBhZXMoZmlsbD10cmFuc3BvcnQsIHk9ZnJlcSwgeD1jb2RlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbj0nZG9kZ2UnLCBzdGF0PSdpZGVudGl0eScpDQoNCmdncGxvdGx5KGNoYXJ0cykNCmBgYA0KDQojIyBSZWNvbW1lZG5hdGlvbjoNCkJhc2VkIG9uIHRoZSBkYXRhIGNvbWFwcmlzb25zIG9mIG1ldHJvIGVudHJpZXMgYWRuIGJpa2UgZW50cmllcywgd2Ugd291bGQgcmVjb21tZW5kIHRoYXQgdGhlIGJpa2VzaGFyZSBncm91cCBsb29rIGludG8gaW5jcmVhc2luZyB0aGUgYW1vdW50IG9mIGJpa2Ugc3RhdGlvbnMgaW4gbmVpZ2hib29yaG9vZHM6IG4xLCBuMiwgbjMsIG40LCBuNiwgbjgsIG4xMCwgbjExLCBuMTQsIG4xNSwgbjE2LCBuMjAsIG4yMSwgbjIyLCBuMjYsIG4yNywgbjI4LCBuMzIsIG4zMywgbjM0LCBuMzYsIG4zNywgbjQwLCBuNDEsIG40NSwgbjQ2LCBuNDcsIG40OSwgbjUwLCBuNTEu
======= <<<<<<< HEAD
LS0tDQp0aXRsZTogIkZpbmFsIFByb2plY3QiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBQYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocGx5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShoZXJlKQ0KbGlicmFyeShnZW9qc29uUikNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgDQpsaWJyYXJ5KG1hcHZpZXcpDQpsaWJyYXJ5KGdiZnMpDQpsaWJyYXJ5KHNmKSANCmxpYnJhcnkodG1hcCkNCmxpYnJhcnkodGlkeWNlbnN1cykNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGNvbmZsaWN0ZWQpDQpjb25mbGljdHNfcHJlZmVyKGhlcmU6OmhlcmUpDQpjb25mbGljdHNfcHJlZmVyKGRwbHlyOjpyZW5hbWUpDQpjb25mbGljdHNfcHJlZmVyKGRwbHlyOjpmaWx0ZXIpDQpjb25mbGljdHNfcHJlZmVyKGRwbHlyOjptdXRhdGUpDQoNCmBgYA0KDQojIyBSZWFkaW5nIHRoZSBmaWxlcy4NCg0KTWV0cm8gU3RhdGlvbiBFbnRyYW5jZXMgdG8gbWFwIHRoZSBsb2NhdGlvbiBvZiBtZXRybywgYm9hcmRpbmcgZGF0YSB0byBzaG93IGhvdyBtYW55IHBlb3BsZSBhcmUgdXNpbmcgdGhlIG1ldHJvIHN0YXRpb24sIGFuZCBiaWtlc2hhcmUgdG8gc2hvdyB0aGUgbnVtYmVyIG9mIHBlb3BsZSByaWRpbmcgYmlrZXMuDQoNCkFsbCBkYXRhIGlzIGZyb20gdGhlIG1vbnRoIFNlcHRlbWJlciBiZWNhdXNlIHRoZXJlIGFyZSBubyBtYWpvciBob2xpZGF5cywgdGhlIHdlYXRoZXIgaXMgc3RpbGwgZGVjZW50IGVub3VnaCBmb3IgcGVvcGxlIHRvIHJpZGUgYmlrZXMsIGFuZCB0aGUgbnVtYmVyIG9mIHRvdXJpc3RzLyBwbGVhc3VyZSBiaWtlIHJpZGVycyBhcmUgcmVkdWNlZC4NCg0KRm9yIHRoZSBwdXJwb3NlIG9mIHRoaXMgcHJvamVjdCwgd2UgcGxhbiBvbiBmb2N1c2luZyBvbiB0aGUgY29tbXV0ZXJzLCBhbmQgcGxhbiBvbiBjcmVhdGluZyBtb3JlIGJpa2UgbG9jYXRpb25zIHRvIGJldHRlciBzdWl0IHRoZSBudW1iZXIgb2YgY29tbXV0ZXJzLg0KDQpgYGB7cn0NCm1ldHJvIDwtIEZST01fR2VvSnNvbihoZXJlKCdkYXRhX3JhdycsICdNZXRyb19TdGF0aW9uX0VudHJhbmNlc19pbl9EQy5nZW9qc29uJykpDQptZXRyb1JpZGVycyA8LSByZWFkLmNzdihoZXJlKCAnQm9hcmRpbmdzIGJ5IFJvdXRlIFRhYmxlX0Z1bGwgRGF0YV9kYXRhLmNzdicpKQ0KbWV0cm9Mb2MgPC0gcmVhZC5jc3YoaGVyZSgnZGF0YV9yYXcnLCAnTWV0cm9fU3RhdGlvbnNfUmVnaW9uYWwuY3N2JykpIA0KDQpzZXB0X3JhdyA8LSByZWFkX2NzdihoZXJlKCAnMjAyMzA5LWNhcGl0YWxiaWtlc2hhcmUtdHJpcGRhdGEuY3N2JykpDQoNCm5laWdoID0gc3RfcmVhZChoZXJlKCJkYXRhX3JhdyIsICJEQ19IZWFsdGhfUGxhbm5pbmdfTmVpZ2hib3Job29kcy5nZW9qc29uIikpICU+JSBjbGVhbl9uYW1lcygpDQoNCmBgYA0KDQojIyBDbGVhbmluZyBEYXRhDQoNClRoaXMgZmlsdGVycyB0aGUgZGF0YSBzbyB3ZSBhcmUgb25seSBnZXR0aW5nIGVudHJpZXMgZm9yIHRoZSB3ZWVrZGF5cyBhbmQgbm90IHRoZSB3ZWVrZW5kcywgYXBwZW5kaW5nIGxvY2F0aW9uIHZhcmlhYmxlcyB0byBzdGF0aW9uIG5hbWVzLCBhbmQgY29tYmluaW5nIHJlcGVhdCBzdGF0aW9ucyB3aXRoIGEgc3VtbWVkIGFtb3VudCBvZiBlbnRyaWVzLg0KDQpgYGB7cn0NCiMjIG1ldHJvTG9jID0gbWV0cm9Mb2MgfD4gDQogICMjIHJlbmFtZSgiWCIgPSAiw68uLlgiKQ0KDQptZXRyb0FkZHkgPC0gc3Vic2V0KG1ldHJvTG9jLCBzZWxlY3QgPSBjKE5BTUUsIEFERFJFU1MsIFgsIFkpKXw+DQogIHJlbmFtZSgiU3RhdGlvbiIgPSAiTkFNRSIsICJMb24iID0gIlgiLCAiTGF0IiA9ICJZIikNCg0KbWV0cm9SaWRlcnMkVGltZS5QZXJpb2QgPSBOVUxMDQptZXRyb1JpZGVycyREYXkub2YuV2VlayA9IE5VTEwNCm1ldHJvUmlkZXJzJEhvbGlkYXkgPSBOVUxMDQptZXRyb1JpZGVycyRNb250aCA9IE5VTEwNCm1ldHJvUmlkZXJzJFllYXIgPSBOVUxMDQptZXRyb1JpZGVycyRBdmcuRGFpbHkuRW50cmllcy5Sb3VuZGVkID0gTlVMTA0KDQojIyBtZXRyb1JpZGVycyA9IG1ldHJvUmlkZXJzIHw+DQogIyMgcmVuYW1lKCJTdGF0aW9uIiA9ICLDry4uU3RhdGlvbiIpDQoNCm1ldHJvUjEgPC0gbWV0cm9SaWRlcnMgfD4NCiAgZmlsdGVyKFNlcnZpY2V0eXBlID09ICJXZWVrZGF5IikgfD4NCiAgZGRwbHkoIlN0YXRpb24iLCBudW1jb2x3aXNlKHN1bSkpDQoNCk1FVFJPIDwtIG1lcmdlKHggPSBtZXRyb1IxLCB5ID0gbWV0cm9BZGR5LCBieSA9ICJTdGF0aW9uIikNCg0KZ2xpbXBzZShNRVRSTykNCg0KYGBgDQoNCiMjIENsZWFuaW5nIGJpa2UgZGF0YQ0KDQpiaWtlUjEgaXMgdGhlIGRhdGEgc2V0IG9yaWdpbmF0ZWQgZnJvbSBTZXB0ZW1iZXIgQmlrZXNoYXJlIGRhdGEuIEl0IGlzIGZpbHRlcmVkIHRvIGtlZXAgdGhlIGNvbHVtbnMgInN0YXJ0ZWQgYXQiLCAic3RhcnQgbGF0IiBhbmQgInN0YXJ0X2xuZyIuIE5hLm9taXQgZ2V0cyByaWQgb2YgZXZlcnl0aGluZyBudWxsLCBhbmQgbXV0YXRlIGFkZHMgdGhlIGRhdGUgdG8gd2hlbiBlYWNoIGJpa2UgcmlkZSBzdGFydGVkLg0KDQpiaWtlUjIgaXMgYSBmdXJ0aGVyIGZpbHRlcmluZyBvZiBiaWtlUjEgd2hlcmUgY29vcmRpbmF0ZXMgYXJlIGFkZGVkIHNvIHdlIGNhbiBtYXAgb3V0IHRoZSBiaWtlIHJpZGVycyBzdGFydGluZyBsb2NhdGlvbi4NCg0KYmlrZVIzIGlzIHRoZSBuZXcgZGF0YSBzZXQgd2hlcmUgYmlrZVIyIGFuZCBuZWlnaCBhcmUgam9pbmVkLiANCg0KYGBge3J9DQpiaWtlUjEgPSBzZXB0X3JhdyAlPiUgc2VsZWN0KHN0YXJ0ZWRfYXQsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKSAlPiUgbmEub21pdCgpICU+JSBtdXRhdGUoc3RhcnRfZGF0ZT1hcy5EYXRlKHN0YXJ0ZWRfYXQpKSAlPiUgc2VsZWN0KHN0YXJ0X2RhdGUsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKQ0KDQpiaWtlUjIgPSBiaWtlUjEgJT4lIHN0X2FzX3NmKGNvb3Jkcz1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycz00MzI2KQ0KDQpzdF9jcnMobmVpZ2gkZ2VvbWV0cnlbMV0pDQoNCmJpa2VSMyA9IGJpa2VSMiAlPiUgc3Rfam9pbihuZWlnaCkNCg0KDQogDQojY29kZSBmb3IgcG9zc2libGUgZnV0dXJlIG1hcHBpbmcgDQojZGYxX3Nfc2YgPSBkZjFfcyAlPiUgc3RfYXNfc2YoY29vcmRzID1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycyA9IDQzMjYpDQpgYGANCg0KDQojIyBNZXRybyBNYXANCg0KVGhlIGZpcnN0IHBhcnQgb2YgdGhpcyBjb2RlIGNodW5rIGlzIGNvbnZlcnRpbmcgdGhlIG1ldHJvIGRhdGEgZnJhbWUgaW50byBhIHNwYXRpYWwgZGF0YSBmcmFtZS4gDQoNCk1ldHJvTWFwMiBpcyBhIGZpbHRyYXRpb24gb2YgTWV0cm9NYXAgdGhhdCBqb2lucyB0aGUgZGF0YSBzZXQgIm5laWdoIiBhbmQgb21pdHMgYW55IG51bGwgdmFsdWVzLiBUaGVuIGEgdmFyaWFibGUgJ2NvZGUnIGlzIGFkZGVkIHRvIHRoZSBudW1jb2x3aXNlLiBUaGVyZSBhcmUgNTAgJ2NvZGVzJyBjcmVhdGVkIGluIHRoaXMgcHJvY2Vzcy4gVGhlbiBmcm9tIHRob3NlIGNvZGVzLCB3ZSB3aWxsIGRldGVybWluZSByaWRlc2hpcCBmb3IgYm90aCBiaWtlcyBhbmQgbWV0cm8uDQoNCmBgYHtyfQ0KTWV0cm9NYXAgPC0gc3RfYXNfc2YoTUVUUk8sIGNvb3JkcyA9IGMoIkxvbiIsICJMYXQiKSwgY3JzID00MzI2KQ0KDQpNZXRyb01hcDIgPC0gTWV0cm9NYXAgJT4lDQogIHN0X2pvaW4obmVpZ2gpICU+JSBuYS5vbWl0KCkgJT4lDQogIGRkcGx5KCJjb2RlIiwgbnVtY29sd2lzZShzdW0pKQ0KYGBgDQoNCg0KIyMgTW9yZSBGaWx0ZXJpbmcNCg0KbmVpZ2gxIGlzIHRoZSBuZXcgZGF0YSBmcmFtZSBvZiAibmVpZ2giIHdoZXJlIGNvZGUgYW5kIGdlb21ldHJ5IGFyZSB0aGUgY2hvc2VuIHZhcmlhYmxlcyB0byBiZSBrZXB0Lg0KDQpiaWtlIFI0IGlzIGEgZnVydGhlciBmaWx0cmF0aW9uIG9mIGJpa2VSMywgd2hlcmUgc3RhcnQgZGF0ZSwgY29kZSwgZ2VvbWV0cnkgaXMga2VwdCBhbmQgZ2VvbWV0cnkgY29sdW1uIGlzIGRyb3BwZWQuDQoNCmJpa2VSNSBpcyBhbm90aGVyIGZpbHRlciBvZiBuZWlnaDEsIHdoZXJlIGJpa2VSNCBpcyBhZGRlZCAoam9pbmVkKS4gQWRkaXRpb25hbGx5LCBlYWNoIG9mIHRoZSB3ZWVrZW5kIGRhdGVzIGFyZSByZW1vdmVkIGZyb20gdGhlIGRhdGEgc2V0IGFzIHdlIGNob3NlIHRvIG9ubHkgbG9vayBhdCB3ZWVrZGF5IGRhdGEuDQoNCmBgYHtyfQ0KDQpuZWlnaDEgPSBuZWlnaCAlPiUgc2VsZWN0KGNvZGUsIGdlb21ldHJ5KQ0KDQpiaWtlUjQgPSBiaWtlUjMgJT4lIHNlbGVjdChzdGFydF9kYXRlLCBjb2RlLCBnZW9tZXRyeSkgJT4lIHN0X2Ryb3BfZ2VvbWV0cnkoKQ0KDQpiaWtlUjUgPSBuZWlnaDEgJT4lIGZ1bGxfam9pbihiaWtlUjQpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTAyJykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTAzJykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTA5JykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTEwJykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTE2JykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTE3JykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTIzJykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTI0JykpICU+JSBmaWx0ZXIoc3RhcnRfZGF0ZSAhPSBhcy5EYXRlKCcyMDIzLTA5LTMwJykpDQpgYGANCiMjIEFuZCBNb3JlIQ0KDQpiaWtlUjYgaXMgYSBucmUgZGF0YSBmcmFtZSB3aGVyZSB3ZSB0b29rIHRoZSBiaWtlIGRhdGEgZnJvbSBzZXQgYmlrZVI1LiBiaWtlUjYgaGFzIDUxIGNvZGVzIGFuZCB0aGV5IGFyZSBsaXN0ZWQgYXMgb2JzZXJ2YXRpb25zLiBBbGwgbnVsbCB2YWx1ZXMgYXJlIG9tbWl0dGVkLg0KDQpiaWtlUjcgdGFrZXMgdGhlIGRhdGEgZnJvbSBiaWtlUjYgYW5kIGtlZXBzIHRoZSBjb2RlIGFzIHdlbGwgYXMgZnJlcXVlbmN5IGFuZCByZW5hbWVzIGl0IHRvIGJpa2VfZnJlcS4gDQoNCmBgYHtyfQ0KI3Bsb3QobmVpZ2gpDQoNCmJpa2VSNiA9IGRhdGEuZnJhbWUodGFibGUoYmlrZVI1JGNvZGUpKSAlPiUgcmVuYW1lKGNvZGU9VmFyMSkgJT4lIGZ1bGxfam9pbihiaWtlUjUpICU+JSBzZWxlY3QoY29kZSwgRnJlcSwgZ2VvbWV0cnkpICU+JSBkaXN0aW5jdCgpICU+JSBuYS5vbWl0KCkNCg0KYmlrZVI3ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoYmlrZV9mcmVxID0gRnJlcSkNCg0KTWV0cm9NYXAzID0gTWV0cm9NYXAyICU+JSBzZWxlY3QoRW50cmllcywgY29kZSkgJT4lIHJlbmFtZShtZXRyb19mcmVxID0gRW50cmllcykNCg0KbWV0cm9fYmlrZV9kZiA9IGJpa2VSNyAlPiUgZnVsbF9qb2luKE1ldHJvTWFwMykgJT4lIG11dGF0ZShtZXRyb19mcmVxID0gcmVwbGFjZV9uYShtZXRyb19mcmVxLCAwKSkNCg0KI2Jpa2VSNyA9IGJpa2VSNSAlPiUgY291bnQoY29kZSwgc3RhcnRfZGF0ZSkNCg0KI3Bsb3QoYmlrZVI2KQ0KYGBgDQojIyBMYXN0IE9uZSENCg0KYmlrZVI4IHRha2VzIGJpa2VSNiBhbmQga2VlcHMgdGhlIGNvZGUgYW5kIGZyZXF1ZW5jeS4gSXQgYWxzbyBjcmVhdGVzIGEgY29sdW1uIGNhbGxlZCBiaWtlIGJlY2F1c2UgYWxsIHRoZSBkYXRhIGluIHRoaXMgc2V0IGlzIGZyb20gYmlrZSByaWRlcnMuIFdlIHdpbGwgdXNlIHRoaXMgY29sdW1uIGxhdGVyIHdoZW4gd2UgbWFrZSBvdXIgdmlzdWFsLiANCg0KTWV0cm9NYXA0IGNvbnRpbnVlcyB0aGUgZmlsdHJhdGlvbiBvZiBNZXRyb01hcDIgd2hlcmUgZW50cmllcyAobGF0ZXIgcmVuYW1lZCB0byBmcmVxKSBhbmQgY29kZSBhcmUga2VwdC4gRXZlcnkgZGF0YSBpbiB0aGlzIHNldCBpcyBnaXZlbiB0aGUgdmFyaWFibGUgJ21ldHJvJyBhcyB0aGV5IHJlcHJlc2VudCBhIG1ldHJvIHJpZGVyLg0KDQpgYGB7cn0NCmJpa2VSOCA9IGJpa2VSNiAlPiUgc2VsZWN0IChjb2RlLCBGcmVxKSAlPiUgcmVuYW1lKGZyZXEgPSBGcmVxKSAlPiUgbXV0YXRlKHRyYW5zcG9ydCA9ICdiaWtlJykNCg0KTWV0cm9NYXA0ID0gTWV0cm9NYXAyICU+JSBzZWxlY3QoRW50cmllcywgY29kZSkgJT4lIHJlbmFtZShmcmVxID0gRW50cmllcykgJT4lIG11dGF0ZSh0cmFuc3BvcnQgPSAnbWV0cm8nKQ0KDQpjb2RlID0gYygiTjEiLCAiTjEwIiwgIk4xMSIsICJOMTQiLCAiTjE1IiwgIk4xNiIsICJOMiIsICJOMjAiLCAiTjIxIiwgIk4yMiIsICJOMjYiLCAiTjI3IiwgIk4yOCIsICJOMyIsICJOMzIiLCAiTjMzIiwgIk4zNCIsICJOMzYiLCAiTjM3IiwgIk40IiwgIk40MCIsICJONDEiLCAiTjQ1IiwgIk40NiIsICJONDciLCAiTjQ5IiwgIk41IiwgIk41MCIsICJONTEiLCAiTjYiLCAiTjgiKQ0KDQpmcmVxID0gYygwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwKQ0KDQp0cmFuc3BvcnQgPSBjKCdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycsICdtZXRybycpDQoNCm1ldHJvRXh0cmEgPSBkYXRhLmZyYW1lKGNvZGUsIGZyZXEsIHRyYW5zcG9ydCkNCg0KTWV0cm9NYXA0ID0gTWV0cm9NYXA0ICU+JSByYmluZChtZXRyb0V4dHJhKQ0KDQptZXRyb19iaWtlX2RmMiA9IGJpa2VSOCAlPiUgZnVsbF9qb2luKE1ldHJvTWFwNCkNCg0KYGBgDQoNCg0KIyMgTWFwcGluZyBNZXRybw0KDQpUaGlzIGlzIGEgc2ltcGxlIHZpc3VhbCBvZiB0aGUgbWV0cm8gc3RhdGlvbiBsb2NhdGlvbnMgaW4gREMuDQoNCmBgYHtyfQ0KZW50cmFuY2VzPXN0X3JlYWQoaGVyZSgiTWV0cm9fU3RhdGlvbl9FbnRyYW5jZXNfaW5fREMuZ2VvanNvbiIpKSAlPiUgY2xlYW5fbmFtZXMoKQ0KDQpjbGFzcyhlbnRyYW5jZXMpDQoNCnBsb3QoZW50cmFuY2VzKQ0KYGBgDQoNCiMjIE1hcHBpbmcgQmlrZSBEYXRhDQoNCldlIGNyZWF0ZSBhIGdnIHBsb3Qgb2YgdGhlIGRhdGEgZnJvbSBhYm92ZS4gVGhlIGNvbWJpbmVkIGRhdGEgc2V0IG9mIG1ldHJvIGFuZCBiaWtlIHJpZGVycyAobWV0cm9fYmlrZV9kZjIpLiBXZSB3YW50ZWQgdG8gdmlzdWFsaXplIHRoZSBudW1iZXIgb2YgcGVvcGxlIHdobyBhcmUgcmlkaW5nIHRoZSBtZXRybyB2cyB1c2luZyBiaWtlcyBpbiBlYWNoIG9mIHRoZSAnY29kZXMnLiANCg0KYGBge3J9DQoNCmdncGxvdChtZXRyb19iaWtlX2RmMiwgYWVzKGZpbGw9dHJhbnNwb3J0LCB5PWZyZXEsIHg9Y29kZSkpICsgZ2VvbV9iYXIocG9zaXRpb249J2RvZGdlJywgc3RhdD0naWRlbnRpdHknKQ0KDQpgYGANCg0K
=======
LS0tDQp0aXRsZTogIkZpbmFsIFByb2plY3QiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBQYWNrYWdlcw0KDQpgYGB7cn0NCmxpYnJhcnkocGx5cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShoZXJlKQ0KbGlicmFyeShnZW9qc29uUikNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgDQpsaWJyYXJ5KG1hcHZpZXcpDQpsaWJyYXJ5KGdiZnMpDQpsaWJyYXJ5KHNmKSANCmxpYnJhcnkodG1hcCkNCmxpYnJhcnkodGlkeWNlbnN1cykNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGNvbmZsaWN0ZWQpDQpsaWJyYXJ5KHBsb3RseSkNCmNvbmZsaWN0c19wcmVmZXIoaGVyZTo6aGVyZSkNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OnJlbmFtZSkNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6OmZpbHRlcikNCmNvbmZsaWN0c19wcmVmZXIoZHBseXI6Om11dGF0ZSkNCg0KYGBgDQoNCiMjIFJlYWRpbmcgdGhlIGZpbGVzLg0KDQpNZXRybyBTdGF0aW9uIEVudHJhbmNlcyB0byBtYXAgdGhlIGxvY2F0aW9uIG9mIG1ldHJvLCBib2FyZGluZyBkYXRhIHRvIHNob3cgaG93IG1hbnkgcGVvcGxlIGFyZSB1c2luZyB0aGUgbWV0cm8gc3RhdGlvbiwgYW5kIGJpa2VzaGFyZSB0byBzaG93IHRoZSBudW1iZXIgb2YgcGVvcGxlIHJpZGluZyBiaWtlcy4NCg0KQWxsIGRhdGEgaXMgZnJvbSB0aGUgbW9udGggU2VwdGVtYmVyIGJlY2F1c2UgdGhlcmUgYXJlIG5vIG1ham9yIGhvbGlkYXlzLCB0aGUgd2VhdGhlciBpcyBzdGlsbCBkZWNlbnQgZW5vdWdoIGZvciBwZW9wbGUgdG8gcmlkZSBiaWtlcywgYW5kIHRoZSBudW1iZXIgb2YgdG91cmlzdHMvIHBsZWFzdXJlIGJpa2UgcmlkZXJzIGFyZSByZWR1Y2VkLg0KDQpGb3IgdGhlIHB1cnBvc2Ugb2YgdGhpcyBwcm9qZWN0LCB3ZSBwbGFuIG9uIGZvY3VzaW5nIG9uIHRoZSBjb21tdXRlcnMsIGFuZCBwbGFuIG9uIGNyZWF0aW5nIG1vcmUgYmlrZSBsb2NhdGlvbnMgdG8gYmV0dGVyIHN1aXQgdGhlIG51bWJlciBvZiBjb21tdXRlcnMuDQoNCmBgYHtyfQ0KbWV0cm8gPC0gRlJPTV9HZW9Kc29uKGhlcmUoJ2RhdGFfcmF3JywgJ01ldHJvX1N0YXRpb25fRW50cmFuY2VzX2luX0RDLmdlb2pzb24nKSkNCm1ldHJvUmlkZXJzIDwtIHJlYWQuY3N2KGhlcmUoJ2RhdGFfcmF3JywgJ0JvYXJkaW5ncyBieSBSb3V0ZSBUYWJsZV9GdWxsIERhdGFfZGF0YS5jc3YnKSkNCm1ldHJvTG9jIDwtIHJlYWQuY3N2KGhlcmUoJ2RhdGFfcmF3JywgJ01ldHJvX1N0YXRpb25zX1JlZ2lvbmFsLmNzdicpKSANCg0Kc2VwdF9yYXcgPC0gcmVhZF9jc3YoaGVyZSgnZGF0YV9yYXcnLCAnMjAyMzA5LWNhcGl0YWxiaWtlc2hhcmUtdHJpcGRhdGEuY3N2JykpDQoNCm5laWdoID0gc3RfcmVhZChoZXJlKCJkYXRhX3JhdyIsICJEQ19IZWFsdGhfUGxhbm5pbmdfTmVpZ2hib3Job29kcy5nZW9qc29uIikpICU+JSBjbGVhbl9uYW1lcygpDQoNCmBgYA0KDQojIyBDbGVhbmluZyBEYXRhDQoNClRoaXMgZmlsdGVycyB0aGUgZGF0YSBzbyB3ZSBhcmUgb25seSBnZXR0aW5nIGVudHJpZXMgZm9yIHRoZSB3ZWVrZGF5cyBhbmQgbm90IHRoZSB3ZWVrZW5kcywgYXBwZW5kaW5nIGxvY2F0aW9uIHZhcmlhYmxlcyB0byBzdGF0aW9uIG5hbWVzLCBhbmQgY29tYmluaW5nIHJlcGVhdCBzdGF0aW9ucyB3aXRoIGEgc3VtbWVkIGFtb3VudCBvZiBlbnRyaWVzLg0KDQpgYGB7cn0NCiNtZXRyb0xvYyA9IG1ldHJvTG9jIHw+IA0KICAjcmVuYW1lKCJYIiA9ICLDry4uWCIpDQoNCm1ldHJvQWRkeSA8LSBzdWJzZXQobWV0cm9Mb2MsIHNlbGVjdCA9IGMoTkFNRSwgQUREUkVTUywgWCwgWSkpfD4NCiAgcmVuYW1lKCJTdGF0aW9uIiA9ICJOQU1FIiwgIkxvbiIgPSAiWCIsICJMYXQiID0gIlkiKQ0KDQptZXRyb1JpZGVycyRUaW1lLlBlcmlvZCA9IE5VTEwNCm1ldHJvUmlkZXJzJERheS5vZi5XZWVrID0gTlVMTA0KbWV0cm9SaWRlcnMkSG9saWRheSA9IE5VTEwNCm1ldHJvUmlkZXJzJE1vbnRoID0gTlVMTA0KbWV0cm9SaWRlcnMkWWVhciA9IE5VTEwNCm1ldHJvUmlkZXJzJEF2Zy5EYWlseS5FbnRyaWVzLlJvdW5kZWQgPSBOVUxMDQoNCiNtZXRyb1JpZGVycyA9IG1ldHJvUmlkZXJzIHw+DQogI3JlbmFtZSgiU3RhdGlvbiIgPSAiw68uLlN0YXRpb24iKQ0KDQptZXRyb1IxIDwtIG1ldHJvUmlkZXJzIHw+DQogIGZpbHRlcihTZXJ2aWNldHlwZSA9PSAiV2Vla2RheSIpIHw+DQogIGRkcGx5KCJTdGF0aW9uIiwgbnVtY29sd2lzZShzdW0pKQ0KDQpNRVRSTyA8LSBtZXJnZSh4ID0gbWV0cm9SMSwgeSA9IG1ldHJvQWRkeSwgYnkgPSAiU3RhdGlvbiIpDQoNCmdsaW1wc2UoTUVUUk8pDQoNCmBgYA0KDQpDbGVhbmluZyBiaWtlIGRhdGENCg0KYGBge3J9DQpiaWtlUjEgPSBzZXB0X3JhdyAlPiUgc2VsZWN0KHN0YXJ0ZWRfYXQsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKSAlPiUgbmEub21pdCgpICU+JSBtdXRhdGUoc3RhcnRfZGF0ZT1hcy5EYXRlKHN0YXJ0ZWRfYXQpKSAlPiUgc2VsZWN0KHN0YXJ0X2RhdGUsIHN0YXJ0X2xhdCwgc3RhcnRfbG5nKQ0KDQpiaWtlUjIgPSBiaWtlUjEgJT4lIHN0X2FzX3NmKGNvb3Jkcz1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycz00MzI2KQ0KDQpzdF9jcnMobmVpZ2gkZ2VvbWV0cnlbMV0pDQoNCmJpa2VSMyA9IGJpa2VSMiAlPiUgc3Rfam9pbihuZWlnaCkNCg0KDQogDQojY29kZSBmb3IgcG9zc2libGUgZnV0dXJlIG1hcHBpbmcgDQojZGYxX3Nfc2YgPSBkZjFfcyAlPiUgc3RfYXNfc2YoY29vcmRzID1jKCJzdGFydF9sbmciLCAic3RhcnRfbGF0IiksIGNycyA9IDQzMjYpDQpgYGANCg0KYGBge3J9DQpNZXRyb01hcCA8LSBzdF9hc19zZihNRVRSTywgY29vcmRzID0gYygiTG9uIiwgIkxhdCIpLCBjcnMgPTQzMjYpDQoNCk1ldHJvTWFwMiA8LSBNZXRyb01hcCAlPiUNCiAgc3Rfam9pbihuZWlnaCkgJT4lIG5hLm9taXQoKSAlPiUNCiAgZGRwbHkoImNvZGUiLCBudW1jb2x3aXNlKHN1bSkpDQpgYGANCg0KDQpgYGB7cn0NCg0KbmVpZ2gxID0gbmVpZ2ggJT4lIHNlbGVjdChjb2RlLCBnZW9tZXRyeSkNCg0KYmlrZVI0ID0gYmlrZVIzICU+JSBzZWxlY3Qoc3RhcnRfZGF0ZSwgY29kZSwgZ2VvbWV0cnkpICU+JSBzdF9kcm9wX2dlb21ldHJ5KCkNCg0KYmlrZVI1ID0gbmVpZ2gxICU+JSBmdWxsX2pvaW4oYmlrZVI0KSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wMicpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wMycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0wOScpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xMCcpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xNicpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0xNycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0yMycpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0yNCcpKSAlPiUgZmlsdGVyKHN0YXJ0X2RhdGUgIT0gYXMuRGF0ZSgnMjAyMy0wOS0zMCcpKQ0KYGBgDQoNCmBgYHtyfQ0KI3Bsb3QobmVpZ2gpDQoNCmJpa2VSNiA9IGRhdGEuZnJhbWUodGFibGUoYmlrZVI1JGNvZGUpKSAlPiUgcmVuYW1lKGNvZGU9VmFyMSkgJT4lIGZ1bGxfam9pbihiaWtlUjUpICU+JSBzZWxlY3QoY29kZSwgRnJlcSwgZ2VvbWV0cnkpICU+JSBkaXN0aW5jdCgpICU+JSBuYS5vbWl0KCkNCg0KYmlrZVI3ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoYmlrZV9mcmVxID0gRnJlcSkNCg0KTWV0cm9NYXAzID0gTWV0cm9NYXAyICU+JSBzZWxlY3QoRW50cmllcywgY29kZSkgJT4lIHJlbmFtZShtZXRyb19mcmVxID0gRW50cmllcykNCg0KbWV0cm9fYmlrZV9kZiA9IGJpa2VSNyAlPiUgZnVsbF9qb2luKE1ldHJvTWFwMykgJT4lIG11dGF0ZShtZXRyb19mcmVxID0gcmVwbGFjZV9uYShtZXRyb19mcmVxLCAwKSkNCg0KI2Jpa2VSNyA9IGJpa2VSNSAlPiUgY291bnQoY29kZSwgc3RhcnRfZGF0ZSkNCg0KI3Bsb3QoYmlrZVI2KQ0KYGBgDQoNCmBgYHtyfQ0KYmlrZVI4ID0gYmlrZVI2ICU+JSBzZWxlY3QgKGNvZGUsIEZyZXEpICU+JSByZW5hbWUoZnJlcSA9IEZyZXEpICU+JSBtdXRhdGUodHJhbnNwb3J0ID0gJ2Jpa2UnKQ0KDQpNZXRyb01hcDQgPSBNZXRyb01hcDIgJT4lIHNlbGVjdChFbnRyaWVzLCBjb2RlKSAlPiUgcmVuYW1lKGZyZXEgPSBFbnRyaWVzKSAlPiUgbXV0YXRlKHRyYW5zcG9ydCA9ICdtZXRybycpDQoNCmNvZGUgPSBjKCJOMSIsICJOMTAiLCAiTjExIiwgIk4xNCIsICJOMTUiLCAiTjE2IiwgIk4yIiwgIk4yMCIsICJOMjEiLCAiTjIyIiwgIk4yNiIsICJOMjciLCAiTjI4IiwgIk4zIiwgIk4zMiIsICJOMzMiLCAiTjM0IiwgIk4zNiIsICJOMzciLCAiTjQiLCAiTjQwIiwgIk40MSIsICJONDUiLCAiTjQ2IiwgIk40NyIsICJONDkiLCAiTjUiLCAiTjUwIiwgIk41MSIsICJONiIsICJOOCIpDQoNCmZyZXEgPSBjKDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDApDQoNCnRyYW5zcG9ydCA9IGMoJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJywgJ21ldHJvJykNCg0KbWV0cm9FeHRyYSA9IGRhdGEuZnJhbWUoY29kZSwgZnJlcSwgdHJhbnNwb3J0KQ0KDQpNZXRyb01hcDQgPSBNZXRyb01hcDQgJT4lIHJiaW5kKG1ldHJvRXh0cmEpDQoNCm1ldHJvX2Jpa2VfZGYyID0gYmlrZVI4ICU+JSBmdWxsX2pvaW4oTWV0cm9NYXA0KQ0KDQpgYGANCg0KDQojIyBNYXBwaW5nIE1ldHJvDQoNCmBgYHtyfQ0KZW50cmFuY2VzPXN0X3JlYWQoaGVyZSgiTWV0cm9fU3RhdGlvbl9FbnRyYW5jZXNfaW5fREMuZ2VvanNvbiIpKSAlPiUgY2xlYW5fbmFtZXMoKQ0KDQpjbGFzcyhlbnRyYW5jZXMpDQoNCnBsb3QoZW50cmFuY2VzKQ0KYGBgDQoNCiMjIE1hcHBpbmcgQmlrZSBEYXRhDQoNCg0KYGBge3J9DQpjaGFydHMgPC0gZ2dwbG90KG1ldHJvX2Jpa2VfZGYyLCBhZXMoZmlsbD10cmFuc3BvcnQsIHk9ZnJlcSwgeD1jb2RlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbj0nZG9kZ2UnLCBzdGF0PSdpZGVudGl0eScpDQoNCmdncGxvdGx5KGNoYXJ0cykNCmBgYA0KDQo=
>>>>>>> 36321748959043dd50b7a89e48066d2758840639 >>>>>>> 4a9cf7e2d8a26172f5a058e785327833a84c65ed